package com.battery.minapp.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipayEncrypt;
import com.alipay.api.response.AlipayFundAuthOperationDetailQueryResponse;
import com.battery.common.core.domain.entity.SysDictData;
import com.battery.common.enums.*;
import com.battery.common.utils.BatteryJSONResult;
import com.battery.common.utils.DateUtils;
import com.battery.common.utils.MapUtils;
import com.battery.common.utils.ali.AliPayEntity;
import com.battery.common.utils.ali.AliPayUtils;
import com.battery.minapp.config.properties.AliPayResource;
import com.battery.minapp.redis.lock.RedisCommonLock;
import com.battery.minapp.redis.lock.RedisKeyHelper;
import com.battery.minapp.utils.WsDevUtils;
import com.battery.system.domain.*;
import com.battery.system.domain.VO.BatteryNumber;
import com.battery.system.domain.VO.StoreVO;
import com.battery.system.domain.VO.UsedLineVO;
import com.battery.system.domain.VO.UsedVO;
import com.battery.system.service.ISysConfigService;
import com.battery.system.service.battery.*;
import org.apache.commons.lang3.StringUtils;
import org.n3r.idworker.Sid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

/**
 * 支付宝小程序
 */
@RestController
@RequestMapping("/ali/")
public class AliApiController {


    @Autowired
    private IAdvertService advertService;


    @Autowired
    private AliPayResource aliPayResource;

    private AliPayEntity _callApi() {
        AliPayEntity entity = new AliPayEntity();
        entity.setAppId(aliPayResource.getAppId());
        entity.setAlipayPublicKey(aliPayResource.getAlipayPublicKey());
        entity.setCharset(aliPayResource.getCharset());
        entity.setGatewayUrl(aliPayResource.getGatewayUrl());
        entity.setMerchantPrivateKey(aliPayResource.getMerchantPrivateKey());
        entity.setSignType(aliPayResource.getSignType());
        entity.setNotifyUrl(aliPayResource.getNotifyUrl());
        entity.setPayeeLogonId(aliPayResource.getPayeeLogonId());
        entity.setPayeeUserId(aliPayResource.getPayeeUserId());
        entity.setFreezeNotifyUrl(aliPayResource.getFreezeNotifyUrl());
        entity.setServiceId(aliPayResource.getServiceId());
        return entity;
    }


    @Autowired
    private IAppUserService appUserService;


    @Autowired
    private Sid sid;


    @Autowired
    private ISysConfigService configService;


    @Autowired
    private IOrderService orderService;


    @Autowired
    private IDeviceService deviceService;


    @Autowired
    private IUsedService usedService;


    @Autowired
    private IStoreInstallService storeInstallService;


    @Autowired
    private IProjectService projectService;


    @Autowired
    private IAuthUsedService authUsedService;


    @Autowired
    private IUsedBasicsService usedBasicsService;


    @Autowired
    private IStoreService storeService;


    @Autowired
    private IRefundOrderService refundOrderService;


    @Autowired
    private IMemberService memberService;

    /**
     * 根据code获取用户信息
     *
     * @param obj
     * @return
     */
    @PostMapping("aliAuthCode")
    public BatteryJSONResult aliAuthCode(@RequestBody JSONObject obj) {
        String code = obj.getString("code");
        if (StringUtils.isBlank(code)) {
            return BatteryJSONResult.errorMsg("code is null");
        }
        AliPayEntity entity = _callApi();
        BatteryJSONResult result = AliPayUtils.getUserId(entity, code);
        if (result.getCode().intValue() != 1) {
            return BatteryJSONResult.errorMsg(result.getMsg());
        }
        String aliUserId = (String) result.getData();
        AppUser appUser = appUserService.selectByOpenId(aliUserId);
        if (appUser == null) {
            // 该用户不存在，则新增用户
            appUser = new AppUser();
            appUser.setId(sid.nextShort());
            appUser.setAppUserCode(aliUserId);
            appUser.setUserType(UserTypeEnum.ALI.getCode());
            appUser.setCreateTime(DateUtils.getNowDate());
            appUserService.insertSelective(appUser);
        }
        JSONObject requestJson = new JSONObject();
        requestJson.put("openid", aliUserId);
        requestJson.put("uid", appUser.getId());
        return BatteryJSONResult.ok(requestJson);
    }


    /**
     * 获取用户授权的基本信息
     *
     * @param jsonObject
     * @return
     */
    @PostMapping("updateUserInfo")
    public BatteryJSONResult updateUserInfo(@RequestBody JSONObject jsonObject) {
        String openid = jsonObject.getString("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("openid is null");
        }

        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录！");
        }

        String userInfo = jsonObject.getString("userinfo");
        if (StringUtils.isBlank(userInfo)) {
            return BatteryJSONResult.errorMsg("未获取到userinfo信息");
        }

        JSONObject userInfoJson = JSON.parseObject(userInfo);
        if (userInfoJson == null) {
            return BatteryJSONResult.errorMsg("userinfo信息不存在");
        }

        JSONObject responseJsonStep1 = JSON.parseObject(userInfoJson.getString("response"));
        JSONObject responseJsonStep2 = JSON.parseObject(responseJsonStep1.getString("response"));
        if (responseJsonStep2 == null) {
            return BatteryJSONResult.errorMsg("userinfo信息不存在");
        }

        String gender = responseJsonStep2.getString("gender");
        String province = responseJsonStep2.getString("province");
        String city = responseJsonStep2.getString("city");
        String nickName = responseJsonStep2.getString("nickName");
        String avatar = responseJsonStep2.getString("avatar");

        AppUser updateAppUser = new AppUser();
        updateAppUser.setId(appUser.getId());
        updateAppUser.setNickName(nickName);
        updateAppUser.setCity(city);
        updateAppUser.setProvince(province);
        updateAppUser.setAvatar(avatar);
        if ("m".equals(gender)) {
            // 性别，男对应“m”，女对应“f”。
            updateAppUser.setSex(SexEnum.man.type);
        } else if ("f".equals(gender)) {
            updateAppUser.setSex(SexEnum.woman.type);
        } else {
            updateAppUser.setSex(SexEnum.secret.type);
        }
        appUserService.updateAppUser(updateAppUser);
        JSONObject requestJson = new JSONObject();
        requestJson.put("uid", appUser.getId());
        return BatteryJSONResult.ok(requestJson);
    }


    /**
     * 校验用户是否授权
     *
     * @param request
     * @return
     */
    @PostMapping("checkAuth")
    public BatteryJSONResult checkAuth(HttpServletRequest request) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("openid信息不存在");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }
        JSONObject requestJson = new JSONObject();
        if (StringUtils.isNotBlank(appUser.getNickName())
                || StringUtils.isNotBlank(appUser.getAvatar())
                || StringUtils.isNotBlank(appUser.getCity())
                || StringUtils.isNotBlank(appUser.getProvince())) {
            requestJson.put("is_auth", 1);
        } else {
            requestJson.put("is_auth", 0);
        }
        return BatteryJSONResult.ok(requestJson);
    }


    /**
     * 获取用户信息
     *
     * @param request
     * @return
     */
    @PostMapping("getInfo")
    public BatteryJSONResult getInfo(HttpServletRequest request) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("openid信息不存在");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录");
        }
        // TODO -----------------> 押金计算 start
        BigDecimal deposit = BigDecimal.ZERO;
        // TODO TODO  这里展示用户未使用的押金
        List<Order> noUsedDeposits = orderService.noUsedALiDeposit(appUser.getId());
        if (noUsedDeposits != null && noUsedDeposits.size() > 0) {
//            deposit = noUsedDeposit.getTotalFee();
            // TODO 查询该用户正常押金之和
            deposit = orderService.noUsedAliDepositSum(appUser.getId());
        }
        // TODO -----------------> 押金计算 end

        JSONObject requestJson = new JSONObject();
        requestJson.put("tel_", configService.selectConfigByKeyNoCache("sys.minapp.customerTel")); // 客服电话
        requestJson.put("deposit", deposit); // TODO 押金展示
        AppUser responseAppuser = new AppUser();
        responseAppuser.setAvatar(appUser.getAvatar());
        responseAppuser.setNickName(appUser.getNickName());
        responseAppuser.setId(appUser.getId());
        responseAppuser.setAppUserCode(appUser.getAppUserCode());
        responseAppuser.setBalance(appUser.getBalance()); // 用户钱包余额
        requestJson.put("user", responseAppuser);
        return BatteryJSONResult.ok(requestJson);
    }


    /**
     * 获取附近商家信息
     *
     * @param request
     * @param jsonObject
     * @return
     */
    @PostMapping("getShopList")
    public BatteryJSONResult getShopList(HttpServletRequest request, @RequestBody JSONObject jsonObject) {
        // TODO TODO
        BigDecimal longitude = jsonObject.getBigDecimal("longitude");
        BigDecimal latitude = jsonObject.getBigDecimal("latitude");
        Integer isList = jsonObject.getInteger("isList"); // 是否需要分页 （0 否 1 是）

        Map<String, Object> map = new HashMap<>();
        map.put("lng", longitude);
        map.put("lat", latitude);

        List<StoreVO> lists = null;
        if (isList == 1) {
            // 分页查询
            Integer pageSize = jsonObject.getInteger("page_size");
            Integer page = jsonObject.getInteger("page");
            Integer offset = pageSize * (page - 1);
            map.put("offset", offset);
            map.put("pageSize", pageSize);
        }
        // 获取设置的距离
        Integer distance = Integer.parseInt(configService.selectConfigByKeyNoCache("sys.store.distance"));
        map.put("distance", distance);
        lists = storeService.getShopList(map);
        List<StoreVO> storeVOS = null;
        if (isList == 0) {
            if (lists != null && lists.size() > 0) {
                storeVOS = new ArrayList<>();
                int size = lists.size();
                StoreVO storeVO = null;
                for (int i = 0; i < size; i++) {
                    storeVO = lists.get(i);
                    storeVO.setWidth(33);
                    storeVO.setHeight(37);
                    storeVOS.add(storeVO);
                }
            }
            JSONObject object = new JSONObject();
            object.put("list", storeVOS);
            return BatteryJSONResult.ok(object);
        }

        // 分页
        // 查询附近门店个数
        Integer total = storeService.selectStoreCountNear(map);
        if (total == 0) {
            JSONObject object = new JSONObject();
            object.put("list", storeVOS);
            object.put("total", total);
            return BatteryJSONResult.ok(object);
        }

        int size = lists.size();

        storeVOS = new ArrayList<>();
        StoreVO storeVO = null;
        for (int i = 0; i < size; i++) {
            storeVO = lists.get(i);
            storeVO.setWidth(33);
            storeVO.setHeight(37);

            // 一个门店可能有多个设备,直接根据门店ID获取对应设备的在库电池数
            BatteryNumber batteryNumber = deviceService.getWsDevInStockNumByStoreId(storeVO.getId());
            storeVO.setInStock(batteryNumber.getInStock()); // 在库电池
            storeVO.setNotInStock(batteryNumber.getAllBattery() - batteryNumber.getInStock()); // 空卡槽位置

            storeVOS.add(storeVO);
        }

        JSONObject object = new JSONObject();
        object.put("list", storeVOS);
        object.put("total", total);
        return BatteryJSONResult.ok(object);
    }

    /**
     * 获取店铺详情
     *
     * @param request
     * @param jsonObject
     * @return
     */
    @PostMapping("getShopInfo")
    public BatteryJSONResult getShopInfo(HttpServletRequest request, @RequestBody JSONObject jsonObject) {
        BigDecimal longitude = jsonObject.getBigDecimal("longitude");
        BigDecimal latitude = jsonObject.getBigDecimal("latitude");
        String storeId = jsonObject.getString("id");

        Store store = storeService.selectByPrimaryKey(storeId);

        StoreVO storeVO = new StoreVO();
        storeVO.setId(storeId);
        storeVO.setStoreName(store.getStoreName());
        storeVO.setDoorPhoto(store.getDoorPhoto());
        storeVO.setLocation(store.getLocation());
        storeVO.setDetailAddress(store.getDetailAddress());
        storeVO.setDistance((float) MapUtils.GetDistance(latitude.doubleValue(), longitude.doubleValue(), store.getLatitude().doubleValue(), store.getLongitude().doubleValue())); //

        BatteryNumber batteryNumber = deviceService.getWsDevInStockNumByStoreId(storeVO.getId());
        storeVO.setInStock(batteryNumber.getInStock()); // 在库电池
        storeVO.setNotInStock(batteryNumber.getAllBattery() - batteryNumber.getInStock()); // 空卡槽位置

        return BatteryJSONResult.ok(storeVO);
    }


    /**
     * 退押金操作
     *
     * @param request
     * @return
     */
    @PostMapping("returnDeposit")
    public BatteryJSONResult returnDeposit(HttpServletRequest request) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }

        List<Used> onLoanUsed = usedService.selectOnLoan(appUser.getId());
        if (onLoanUsed != null && onLoanUsed.size() > 0) {
            return BatteryJSONResult.errorMsg("存在正在借用中的订单！可在个人中心我的订单查看");
        }

        // TODO  暂时不能在这里退押 , 为了保证不会错乱
        return BatteryJSONResult.errorMsg("存在正在借用中的订单！可在个人中心我的订单查看");

//        List<Order> noUsedDeposits = orderService.noUsedALiDeposit(appUser.getId());
//        if (noUsedDeposits == null) {
//            return BatteryJSONResult.errorMsg("您的押金不存在，如有疑问请联系客服！");
//        }
//
//        // TODO 退押金一个一个退
//        Order noUsedDeposit = noUsedDeposits.get(0);
//
//        String key = RedisKeyHelper.getAliRefundDepositKey(openid);
//        boolean lock = RedisCommonLock.commonLock(key);
//        if (!lock) {
//            return BatteryJSONResult.errorMsg("系统繁忙，请稍后在试");
//        }
//
//        try {
//            BigDecimal balance = appUser.getBalance();
//            BigDecimal refund_fee = null; // 退款金额
//            if (balance.compareTo(BigDecimal.ZERO) < 0) {
//                BigDecimal absBalance = balance.abs();
//                // 存在欠款金额
//                refund_fee = noUsedDeposit.getTotalFee().subtract(absBalance);
//            } else {
//                refund_fee = noUsedDeposit.getTotalFee();
//            }
//
//            if (refund_fee.compareTo(BigDecimal.ZERO) <= 0) {
//                return BatteryJSONResult.errorMsg("您的押金已使用完毕");
//            }
//
//            AliPayEntity entity = _callApi();
//            return refundOrderService.aliRefundDeposit(appUser, noUsedDeposit, refund_fee, entity);
//        } catch (Exception e) {
//            e.printStackTrace();
//            return BatteryJSONResult.errorMsg("系统繁忙，请稍后再试");
//        } finally {
//            RedisCommonLock.unlock(key);
//        }
    }


    /**
     * 获取用户使用记录
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("usedList")
    public BatteryJSONResult usedList(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }

        Integer pageSize = obj.getInteger("page_size");
        Integer page = obj.getInteger("page");
        Integer offset = pageSize * (page - 1);

        Date lastMonth = DateUtils.getDateLastMonth(new Date());
        Map<String, Object> map = new HashMap<>();
        map.put("appUserId", appUser.getId());
        map.put("offset", offset);
        map.put("pageSize", pageSize);
        map.put("limitDate", lastMonth);
        List<UsedVO> lists = usedService.selectListByMap(map);
//        Integer total = usedService.selectCountLastMonth(appUser.getId(), lastMonth);
        Integer total = usedService.selectListByMapCout(map);
        List<UsedVO> thisLists = null;
        if (lists != null && lists.size() > 0) {
            thisLists = new ArrayList<>();
            Date date = DateUtils.getNowDate();
            int size = lists.size();
            UsedVO usedVO = null;
            for (int i = 0; i < size; i++) {
                usedVO = lists.get(i);
                usedVO.setUsedTypeMsg("机柜订单");
                if (DevTypeEnum.WS_DEV_4.getCode().equals(usedVO.getDevType())) {
                    usedVO.setDevTypeMsg(DevTypeEnum.WS_DEV_4.getValue());
                } else if (DevTypeEnum.WS_DEV_6.getCode().equals(usedVO.getDevType())) {
                    usedVO.setDevTypeMsg(DevTypeEnum.WS_DEV_6.getValue());
                } else if (DevTypeEnum.WS_DEV_12.getCode().equals(usedVO.getDevType())) {
                    usedVO.setDevTypeMsg(DevTypeEnum.WS_DEV_12.getValue());
                } else if (DevTypeEnum.WS_DEV_9.getCode().equals(usedVO.getDevType())) {
                    usedVO.setDevTypeMsg(DevTypeEnum.WS_DEV_9.getValue());
                } else if (DevTypeEnum.R_LINE.getCode().equals(usedVO.getDevType())) {
                    usedVO.setDevTypeMsg(DevTypeEnum.R_LINE.getValue());
                    usedVO.setUsedTypeMsg("线订单");
                } else {
                    usedVO.setUsedTypeMsg("其他设备");
                }
                if (usedVO.getLeaseState() == 1) {
                    // 租借成功
                    if (usedVO.getIsBack() == 1) {
                        date = usedVO.getBackDate();
                    }
                    usedVO.setUseTime(DateUtils.getDatePoor(date, usedVO.getRentDate()));
                }
                thisLists.add(usedVO);
            }
        }
        JSONObject object = new JSONObject();
        object.put("total", total);
        object.put("list", thisLists);
        return BatteryJSONResult.ok(object);
    }


    /**
     * 根据使用记录id， 获取该使用记录的详细信息
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("getUsedInfo")
    public BatteryJSONResult getUsedInfo(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }
        String used_id = obj.getString("used_id");
        UsedVO usedVO = usedService.getUsedInfoById(used_id);
        return BatteryJSONResult.ok(usedVO);
    }

    /**
     * 校验设备类型
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("checkDeviceType")
    public BatteryJSONResult checkDeviceType(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }
        String sn = obj.getString("sn");
        if (StringUtils.isBlank(sn)) {
            return BatteryJSONResult.errorMsg("机柜SN不存在!");
        }
        Device device = deviceService.selectBySn(sn);
        if (device == null) {
            return BatteryJSONResult.errorMsg("该设备未激活!");
        }

        Integer isDisable = device.getIsDisable();
        if (YesOrNoEnum.YES.getCode().intValue() == isDisable.intValue()) {
            return BatteryJSONResult.errorMsg("该设备已被禁止使用!");
        }

        int type = 0;
        JSONObject requestJson = new JSONObject();
        if (!device.getDevType().contains("DEV")) {
            // TODO 线设备 ---> DEV 为机柜设备 LINE 线设备 注意设备是否被删除了
            type = 1;
        }
        requestJson.put("sn", sn);
        requestJson.put("type", type);
        return BatteryJSONResult.ok(requestJson);
    }


    /**
     * 扫码租借机柜设备(第一步骤)
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("deviceFirstStep")
    public BatteryJSONResult deviceFirstStep(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }

        String sn = obj.getString("sn");
        Device device = deviceService.selectBySn(sn);
        if (device == null) {
            return BatteryJSONResult.errorMsg("该设备未激活!");
        }
        // 判断该设备是否签约了商户
//        if (StringUtils.isBlank(device.getMerchantId()) || "0".equals(device.getMerchantId())) {
//            return BatteryJSONResult.errorMsg("该设备未签约商户,请联系商户!");
//        }

        // 查询该用户是否存在借用中的订单
//        List<Used> onLoanUsed = usedService.selectOnLoan(appUser.getId());
//        if (onLoanUsed != null && onLoanUsed.size() > 0) {
//            return BatteryJSONResult.errorMsg("存在正在借用中的订单！可在个人中心我的订单查看");
//        }
        // TODO TOOD 查询该用户正在租借中的订单个数
        int freeDeposit = 1; // 免押租借
        int inBorrowUsed = usedService.selectOnLoanCountByUid(appUser.getId());
        if (inBorrowUsed > 0) {
            // 存在正在租借中的订单
            int controlInBorrow = Integer.parseInt(configService.selectConfigByKeyNoCache("sys.borrow.control")); // 用户租借次数限制
            if (controlInBorrow == inBorrowUsed) {
                return BatteryJSONResult.errorMsg("您租借次数已达上限");
            }
            // 交押金限制
            int needToYz = Integer.parseInt(configService.selectConfigByKeyNoCache("sys.borrow.needToYz"));
            if (inBorrowUsed >= needToYz) {
                // 达到上限需要交押金
                freeDeposit = 0;
            }
        }


        boolean needAuthPhone = false;
        // 判断用户是否已经授权手机号
        if (StringUtils.isBlank(appUser.getMobile())) {
            Integer authPhoneNeedCount = Integer.parseInt(configService.selectConfigByKeyNoCache("sys.appuser.ali.warrantphone"));
            if (authPhoneNeedCount >= 0) {
                // 查询该用户租借次数
                Integer borrowCount = usedService.selectBorrowCount(appUser.getId());
                if (borrowCount >= authPhoneNeedCount) {
                    // 用于需要授权手机号
                    needAuthPhone = true;
                }
            }
        }

        Project project = projectService.selectByPrimaryKey(device.getProjectId());
        BigDecimal deposit = new BigDecimal(99);
        if (project != null) {
            deposit = project.getDeposit();
        }

        JSONObject requestJson = new JSONObject();
        requestJson.put("sn", sn);
        requestJson.put("deposit", deposit);


        if (needAuthPhone) {
            // 需要授权手机号
            requestJson.put("need_tel", 1);
            requestJson.put("need_tel_tip_1", configService.selectConfigByKeyNoCache("sys.authtel.but.tips")); // 页面上授权手机号按钮文字
            requestJson.put("need_tel_tip_2", configService.selectConfigByKeyNoCache("sys.authtel.but.tips2")); // 页面上授权手机号按钮底下文字描述
            requestJson.put("refuse_msg", configService.selectConfigByKeyNoCache("sys.authtel.refuse_msg")); // 用户拒绝授权手机号的提示
            requestJson.put("refuse_show", Integer.parseInt(configService.selectConfigByKeyNoCache("sys.authtel.refuse_show"))); // 拒绝是否需要提示文字 1 为需要 0 为不需要
            requestJson.put("refuse_after_borrow", Integer.parseInt(configService.selectConfigByKeyNoCache("sys.authtel.refuse_after_borrow"))); // 拒绝之后是否可以继续租借 1 可以继续租借 0 不允许继续租借
        } else {
            requestJson.put("need_tel", 0);
        }

        // 门店一系列配置信息
        String mealMsg = "";
        String freeMsg = "";
        BigDecimal price = BigDecimal.ZERO;
        StoreInstall storeInstall = storeInstallService.selectByPrimaryKey(device.getStoreId());
        if (storeInstall == null) {
//            return BatteryJSONResult.errorMsg("该设备未部署");
            price = new BigDecimal(2);
            freeMsg = "前2分钟分钟内免费使用";
            requestJson.put("unit", "元/小时");
            mealMsg = mealMsg + freeMsg + "," + price + "元/小时,每日封顶20元,总封顶" + deposit + "元";

            requestJson.put("freeMsg", freeMsg); //
            requestJson.put("storeName", "仓库"); //
            requestJson.put("storeAddress", "仓库"); //
            requestJson.put("mealMsg_01", "每24小时封顶20元,最高封顶" + deposit + "元");
            requestJson.put("mealMsg_02", "租借时长不足1小时,按1小时计费");
        } else {

            String mealMsg_01 = "每24小时封顶" + storeInstall.getDayMax() + "元,最高封顶" + deposit + "元";
            String mealMsg_02 = "";

            price = storeInstall.getPrice();
            if (storeInstall.getFreeM() > 0) {
                freeMsg = "前" + storeInstall.getFreeM() + "分钟免费,";
            }
            if (DevMealTimeEnum.HALF_HOUR.type.intValue() == storeInstall.getUnitTime().intValue()) {
                requestJson.put("unit", "元/半小时");
                mealMsg = mealMsg + freeMsg + storeInstall.getPrice() + "元/半小时,每日封顶" + storeInstall.getDayMax() + "元,总封顶" + deposit + "元";
                mealMsg_02 = "租借时长不足30分钟,按30分钟计费";
            } else if (DevMealTimeEnum.FIFTEEN_MINUTES.type.intValue() == storeInstall.getUnitTime().intValue()) {
                requestJson.put("unit", "元/15分钟");
                mealMsg = mealMsg + freeMsg + storeInstall.getPrice() + "元/15分钟,每日封顶" + storeInstall.getDayMax() + "元,总封顶" + deposit + "元";
                mealMsg_02 = "租借时长不足15分钟,按15分钟计费";
            } else {
                requestJson.put("unit", "元/小时");
                mealMsg = mealMsg + freeMsg + storeInstall.getPrice() + "元/小时,每日封顶" + storeInstall.getDayMax() + "元,总封顶" + deposit + "元";
                mealMsg_02 = "租借时长不足1小时,按1小时计费";
            }
            if (storeInstall.getFreeM() > 0) {
                requestJson.put("freeMsg", "前" + storeInstall.getFreeM() + "分钟内免费使用"); //
            }
            Store store = storeService.selectByPrimaryKey(storeInstall.getStoreId());
            requestJson.put("storeName", store.getStoreName()); //
            requestJson.put("storeAddress", store.getDetailAddress()); //
            requestJson.put("mealMsg_01", mealMsg_01);
            requestJson.put("mealMsg_02", mealMsg_02);
        }
        // TODO TODO 因为支付宝暂时没有芝麻信用，所以先采用押金租借方式
//        Integer freeDeposit = Integer.parseInt(configService.selectConfigByKeyNoCache("sys.ali.borrow.mode"));
        requestJson.put("freeDeposit", freeDeposit); // TODO 默认全部免押租借  1 免押 0 不免押
        requestJson.put("mealMsg", mealMsg);
        requestJson.put("zmFraction", 550); // 芝麻信用分数
        requestJson.put("tips_1", "充电宝超期未归还，将自动代扣您" + project.getDeposit() + "元");
        requestJson.put("tips_2", configService.selectConfigByKeyNoCache("sys.aliMinApp.tipsOnLoan")); // 展示给用户看的提醒

        // 无法免押租借，是否需要进行伪装
        String showTipValue = "";
        int showTipsNeed = Integer.parseInt(configService.selectConfigByKeyNoCache("sys.ali.borrow.tip.need"));
        if (showTipsNeed == 1) {
            // 需要展示
            showTipValue = configService.selectConfigByKeyNoCache("sys.ali.borrow.tip.value");
        }

        Advert advert = advertService.selectByUseSceneType(1); // 充电宝租借界面
        if (advert != null && advert.getIsClose() == YesOrNoEnum.NO.getCode().intValue()) {
            requestJson.put("isShow", 1);
            requestJson.put("adImg", advert.getImg());
        } else {
            requestJson.put("isShow", 0);
            requestJson.put("adImg", "");
        }
        requestJson.put("price", price);
        requestJson.put("showTipsNeed", showTipsNeed);
        requestJson.put("showTipValue", showTipValue);
        return BatteryJSONResult.ok(requestJson);
    }


    /**
     * 扫码租借机柜设备(第二步骤)
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("deviceBorrow")
    public BatteryJSONResult deviceBorrow(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }

        // 判断该用户是否被冻结使用
        if (appUser.getIsFrozen() == 1) {
            // 该用户被冻结使用
            return BatteryJSONResult.errorMsg("您的账号被冻结。冻结原因:[" + appUser.getReason() + "]!");
        }

        String sn = obj.getString("sn");
        Integer freeDeposit = obj.getInteger("freeDeposit");
        String used_id = obj.getString("used_id"); // 授权租借ID

        // 查询是否存在借用中的订单
//        List<Used> onLoanUsed = usedService.selectOnLoan(appUser.getId());
//        if (onLoanUsed != null && onLoanUsed.size() > 0) {
//            return BatteryJSONResult.errorMsg("存在正在借用中的订单！可在个人中心我的订单查看");
//        }

        Device device = deviceService.selectBySn(sn);
        if (device == null) {
            return BatteryJSONResult.errorMsg("该设备未激活！");
        }

        if (!device.getDevType().contains("DEV")) {
            // 不是机柜设备
            return BatteryJSONResult.errorMsg("请扫机柜上二维码！");
        }


        String devType = device.getDevType();
        if (DevTypeEnum.WS_DEV_4.getCode().equals(devType)
                || DevTypeEnum.WS_DEV_6.getCode().equals(devType)
                || DevTypeEnum.WS_DEV_9.getCode().equals(devType)
                || DevTypeEnum.WS_DEV_12.getCode().equals(devType)) {
            BatteryJSONResult boxStatusResult = WsDevUtils.boxStatus(sn);
            if (boxStatusResult.getCode() == 0) {
                // 设备不在线
                return boxStatusResult;
            }
        } else {
            return BatteryJSONResult.errorMsg("不存在该类型的设备");
        }

        StoreInstall storeInstall = storeInstallService.selectByPrimaryKey(device.getStoreId());


        if (freeDeposit == 0) {
            // 支付宝交押金租借
            // TODO TODO 查询未标记的正常押金
            List<Order> noUsedDeposits = orderService.noUsedALiDepositNoSign(appUser.getId());
            Project project = projectService.selectByPrimaryKey(device.getProjectId());
            BigDecimal deposit = new BigDecimal(99);
            if (project != null) {
                deposit = project.getDeposit();
            }
            if (noUsedDeposits == null) {
                // 该用户未支付押金，第一次租借
                JSONObject requestJsonObj = new JSONObject();
                requestJsonObj.put("amount", deposit);
                requestJsonObj.put("sn", sn);
                return BatteryJSONResult.build(3, "请充值押金", requestJsonObj);
            } else {
//                String key = RedisKeyHelper.getAliBorrowKey(openid);
//                boolean lock = RedisCommonLock.commonLock(key);
//                if (!lock) {
//                    return BatteryJSONResult.errorMsg("系统繁忙，请稍后在试");
//                }
//                try {
                BigDecimal balance = appUser.getBalance();
                if (balance.compareTo(BigDecimal.ZERO) < 0) {
                    // 用户产生了租借费用，需要先支付该笔金额
                    BigDecimal absBalance = balance.abs(); // 用户欠费金额
                    // 获取押金租借的未支付订单
                    Used noPayUsed = usedService.selectOneNoPay(appUser.getId(), UserTypeEnum.ALI.getCode(), BorrowModeEnum.DEPOSIT.type);
                    if (noPayUsed != null) {
                        BigDecimal money = noPayUsed.getAmountPaid();
                        if (absBalance.subtract(money).compareTo(BigDecimal.ZERO) == 0) {
                            // 钱包余额与租借记录的订单金额一致，用户需要支付
                            JSONObject requestJson = new JSONObject();
                            requestJson.put("amount", absBalance); //  用户欠费金额
                            requestJson.put("sn", sn);
                            requestJson.put("used_id", noPayUsed.getId()); // 用户支付
                            return BatteryJSONResult.build(4, "您存在" + absBalance + "元未支付的订单", requestJson);
                        } else {
                            return BatteryJSONResult.errorMsg("租借失败，待付款金额与钱包余额里面金额不一致，请联系管理员");
                        }
                    }
                    return BatteryJSONResult.errorMsg("租借失败，发生错误，未查询到对应的未付款订单");
                } else {
                    // TODO TODO  一笔押金一笔订单
                    if (noUsedDeposits.size() > 0) {
                        Order noUsedDeposit = noUsedDeposits.get(0);
                        // 该用户未产生租借费用，钱包余额为0,且存在押金， 那么可以直接开始租借
                        // 两种租借方式，配合进行
                        BatteryJSONResult result = null;
                        String borrowWay = configService.selectConfigByKeyNoCache("sys.wsDev.borrowWay");
                        if ("2".equals(borrowWay)) {
                            // 传统方式租借+强弹租借(必须保证库存是最新的)
                            result = usedService.wsDevTips2DepositBorrowBattery(noUsedDeposit, appUser, storeInstall, device);
                        } else {
                            // 传统方式租借
                            result = usedService.wsDevTips1DepositBorrowBattery(noUsedDeposit, appUser, storeInstall, device);
                        }
                        return result;
                    } else {
                        // 该用户未支付押金，第一次租借
                        JSONObject requestJsonObj = new JSONObject();
                        requestJsonObj.put("amount", deposit);
                        requestJsonObj.put("sn", sn);
                        return BatteryJSONResult.build(3, "请充值押金", requestJsonObj);
                    }
                }
//                } catch (Exception e) {
//                    e.printStackTrace();
//                    return BatteryJSONResult.errorMsg("系统繁忙，请稍后再试");
//                } finally {
//                    RedisCommonLock.unlock(key);
//                }
            }
        } else {
            // 免押租借
            if (StringUtils.isBlank(used_id)) {
                // 支付宝未授权租借
                Project project = projectService.selectByPrimaryKey(device.getProjectId());
                BigDecimal deposit = new BigDecimal(99);
                if (project != null) {
                    deposit = project.getDeposit();
                }
                JSONObject requestJSON = new JSONObject();
                requestJSON.put("amount", deposit);
                requestJSON.put("sn", sn);
                return BatteryJSONResult.build(3, "创建微信免押订单", requestJSON);
            } else {
                // 查询对应的授权租借订单

                String key = RedisKeyHelper.getAliBorrowKey(openid);
                boolean lock = RedisCommonLock.commonLock(key);
                if (!lock) {
                    return BatteryJSONResult.errorMsg("您点击太频繁，请稍后在试");
                }
                try {
                    AuthUsed authUsed = authUsedService.selectByPrimaryKey(used_id);
                    if (authUsed == null) {
                        return BatteryJSONResult.errorMsg("未查询到对应的授权租借记录");
                    }
                    AliPayEntity entity = _callApi();
                    JSONObject requestQueryObj = new JSONObject();
                    requestQueryObj.put("out_order_no", authUsed.getOutOrderNo());
                    requestQueryObj.put("out_request_no", authUsed.getTicket());
                    BatteryJSONResult responseJSON = AliPayUtils.fundAuthQuery(entity, requestQueryObj, 1);
                    if (responseJSON.getCode() == 0) {
                        // 查询出错
                        return responseJSON;
                    }
                    AlipayFundAuthOperationDetailQueryResponse response = (AlipayFundAuthOperationDetailQueryResponse) responseJSON.getData();
                    String responseStatus = response.getStatus();
                    BigDecimal totalFreezeAmount = new BigDecimal(response.getTotalFreezeAmount());
                    String operation_type = response.getOperationType();
                    if ("FREEZE".equals(operation_type) && totalFreezeAmount.subtract(new BigDecimal(0.01)).compareTo(BigDecimal.ZERO) >= 0 && "SUCCESS".equals(responseStatus)) {
                        BatteryJSONResult result_ = null;
                        String borrowWay = configService.selectConfigByKeyNoCache("sys.wsDev.borrowWay");
                        if ("2".equals(borrowWay)) {
                            // 传统方式租借+强弹租借(必须保证库存是最新的)
                            result_ = usedService.wsDevTips2FreeDepositBorrowBattery(authUsed, appUser, storeInstall, device);
                        } else {
                            result_ = usedService.wsDevTips1FreeDepositBorrowBattery(authUsed, appUser, storeInstall, device);
                        }
                        if (result_.getCode() == 1) {
                            // 租借成功
                            return result_;
                        }
                        // 租借失败，解冻订单 TODO TODO 前端需要进行调整
                        return authUsedService.doUnfreeze(authUsed.getUsedId(), entity);
                    }
                    return BatteryJSONResult.errorMsg("授权租借订单异常");
                } catch (Exception e) {
                    e.printStackTrace();
                    return BatteryJSONResult.errorMsg("系统繁忙，请稍后再试");
                } finally {
                    RedisCommonLock.unlock(key);
                }
            }
        }
    }


    /**
     * 校验订单是否成功
     *
     * @return
     */
    @PostMapping("checkOrderStatus")
    public BatteryJSONResult checkOrderStatus(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }
        String order_id = obj.getString("order_id"); // 如果为免押则order_id为used_id
        Integer freeDeposit = obj.getInteger("freeDeposit"); // 是否免押
        if (freeDeposit == 0) {
            //  支付订单
            Order order = orderService.selectByPrimaryKey(order_id);
            if (order == null) {
                return BatteryJSONResult.errorMsg("未查询到对应的订单");
            }
            String out_trade_no = order.getOutOrderNo();
            AliPayEntity entity = _callApi();
            BatteryJSONResult queryResponse = AliPayUtils.tradeQuery(entity, out_trade_no);
            if (queryResponse.getCode() == 1 && OrderTradeStateEnum.PAY_SUCCESS.getCode().intValue() == (order.getTradeState()).intValue()) {
                // 支付成功
                JSONObject requestJSON = new JSONObject();
                requestJSON.put("status", 1);
                requestJSON.put("order_id", order.getId());
                return BatteryJSONResult.ok(requestJSON);
            }
            // 等待支付回调
            JSONObject requestJSON = new JSONObject();
            requestJSON.put("status", 0);
            requestJSON.put("order_id", order.getId());
            return BatteryJSONResult.ok(requestJSON);
        }
        AuthUsed authUsed = authUsedService.selectByPrimaryKey(order_id);
        if (authUsed == null) {
            return BatteryJSONResult.errorMsg("未查询到对应的授权订单");
        }
        if (UsedAuthStateEnum.DOING.type.equals(authUsed.getState())
                && UsedAuthStateDescriptionEnum.FREEZE.type.equals(authUsed.getStateDescription())) {
            JSONObject requestJSON = new JSONObject();
            requestJSON.put("status", 1);
            requestJSON.put("used_id", authUsed.getUsedId());
            return BatteryJSONResult.ok(requestJSON);
        }
        JSONObject requestJSON = new JSONObject();
        requestJSON.put("status", 1);
        requestJSON.put("used_id", authUsed.getUsedId());
        return BatteryJSONResult.build(1000, "等待预授权回调！请再次点击按钮", requestJSON);
    }


    /**
     * 发起支付宝预授权
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("doFreeze")
    public BatteryJSONResult doFreeze(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }
        BigDecimal amount = obj.getBigDecimal("amount");
        String sn = obj.getString("sn");
        if (amount == null) {
            return BatteryJSONResult.errorMsg("请输入正确的金额!");
        }
        if (amount.subtract(new BigDecimal(0.01)).compareTo(BigDecimal.ZERO) < 0) {
            return BatteryJSONResult.errorMsg("金额不能小于0.01");
        }
        Device device = deviceService.selectBySn(sn);
        if (device == null) {
            return BatteryJSONResult.errorMsg("该设备未激活!");
        }
        String key = RedisKeyHelper.getAliDoFreeKey(openid);
        boolean lock = RedisCommonLock.commonLock(key);
        if (!lock) {
            return BatteryJSONResult.errorMsg("您点击太频繁，请稍后在试");
        }
        try {
            StoreInstall storeInstall = storeInstallService.selectByPrimaryKey(device.getStoreId());
            AliPayEntity entity = _callApi();
            return authUsedService.doFreeze(appUser, device, storeInstall, amount, entity);
        } catch (Exception e) {
            e.printStackTrace();
            return BatteryJSONResult.errorMsg("您点击太频繁，请稍后再试");
        } finally {
            RedisCommonLock.unlock(key);
        }
    }


    /**
     * 支付宝发起支付 - 统一下单
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("alipayRecharge")
    public BatteryJSONResult alipayRecharge(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }

        BigDecimal amount = obj.getBigDecimal("amount");
        String sn = obj.getString("sn"); // 必传项, TODO 如果为充值，则为 RECHARGE 后续在考虑充值
        Integer type = obj.getInteger("type"); // 1 押金  2 机柜租赁费用 3 线租借费用 // 订单类型: 押金 机柜租赁费用 线租借费用
        String extra = obj.getString("extra"); // 额外参数 // 如果是机柜租赁费用，则该额外参数为 used_id

        // 支付押金 以及线租借必然会携带机柜SN信息
        if (StringUtils.isBlank(sn)) {
            return BatteryJSONResult.errorMsg("必填项SN为空");
        }

        Device device = deviceService.selectBySn(sn);
        if (device == null) {
            return BatteryJSONResult.errorMsg("未查询到对应的设备信息！");
        }

        String key = RedisKeyHelper.getAliPayRechargeKey(openid);
        boolean lock = RedisCommonLock.commonLock(key);
        if (!lock) {
            return BatteryJSONResult.errorMsg("系统繁忙，请稍后在试");
        }
        try {
            AliPayEntity entity = _callApi();
            return orderService.aliPayRecharge(appUser, device, amount, type, extra, entity);
        } catch (Exception e) {
            e.printStackTrace();
            return BatteryJSONResult.errorMsg("系统繁忙，请稍后再试");
        } finally {
            RedisCommonLock.unlock(key);
        }


    }


    /**
     * 查询电池是否租借成功
     *
     * @return
     */
    @PostMapping("checkUsed")
    public BatteryJSONResult checkUsed(@RequestBody JSONObject obj) {
        String used_id = obj.getString("used_id");
        Used used = usedService.selectByPrimaryKey(used_id);
        if (used == null) {
            return BatteryJSONResult.errorMsg("查询电池是否租借成功-未查找到对应的租借订单");
        }
        if (LeaseStateEnum.SUCCESS.getCode() == used.getLeaseState()) {
            // 租借成功
            JSONObject requestJSONObj = new JSONObject();
            requestJSONObj.put("status", 1);
            requestJSONObj.put("used_id", used_id);
            return BatteryJSONResult.ok(requestJSONObj);
        } else {
            JSONObject requestJSONObj = new JSONObject();
            requestJSONObj.put("status", 0);
            requestJSONObj.put("used_id", used_id);
            return BatteryJSONResult.ok(requestJSONObj);
        }
    }


    /**
     * 查询使用记录-（使用于租借成功或者失败页面）
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("getUsed")
    public BatteryJSONResult getUsed(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录");
        }
        String used_id = obj.getString("used_id");
        UsedBasics usedBasics = usedBasicsService.selectByPrimaryKey(used_id);
        Used used = usedService.selectByPrimaryKey(used_id);

        JSONObject requestJSON = new JSONObject();
        requestJSON.put("lendTime", usedBasics.getRentDate()); // 借出时间
        requestJSON.put("mealName", used.getMealContent());
        requestJSON.put("used_id", used_id);
        requestJSON.put("usedSn", used.getOrderNumber()); // 订单号
        requestJSON.put("sceneName", used.getStoreName());
        requestJSON.put("batterySn", usedBasics.getBatterySn());
        return BatteryJSONResult.ok(requestJSON);
    }


    /**
     * 支付宝预授权订单解冻
     *
     * @return
     */
    @PostMapping("doUnfreeze")
    public BatteryJSONResult doUnfreeze(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录");
        }
        String used_id = obj.getString("used_id");
        // 更新租借状态为失败，如果是授权订单，则撤销
        AliPayEntity entity = _callApi();
        return authUsedService.doUnfreeze(used_id, entity);
    }


    /**
     * 获取帮助信息
     *
     * @param request
     * @return
     */
    @PostMapping("/getHelps")
    public BatteryJSONResult getHelps(HttpServletRequest request) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }
        JSONArray arr = new JSONArray();
        // 查看使用帮助内容
        List<SysDictData> helps = configService.selectDictDataByType("sys_minapp_helps");
        if (helps != null && helps.size() > 0) {
            // 存在帮助信息
            int size = helps.size();
            SysDictData dictData = null;
            JSONObject object = null;
            for (int i = 0; i < size; i++) {
                dictData = helps.get(i);
                object = new JSONObject();
                object.put("helpTitle", dictData.getDictLabel());
                object.put("helpContent", dictData.getDictValue());
                arr.add(i, object);
            }
        }
        return BatteryJSONResult.ok(arr);
    }


    /**
     * 订单未支付-->发起支付
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("doToPay")
    public BatteryJSONResult doToPay(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }

        String used_id = obj.getString("used_id");
        String order_id = obj.getString("order_id");

        Used used = usedService.selectByPrimaryKey(used_id);
        if (used == null) {
            return BatteryJSONResult.errorMsg("未查询到对应的租借订单");
        }
        BigDecimal money = used.getAmountPaid();
        if (money.compareTo(BigDecimal.ZERO) == 0) {
            return BatteryJSONResult.errorMsg("金额为0，无需支付");
        }

        if (StringUtils.isBlank(order_id)) {
            UsedBasics basics = usedBasicsService.selectByPrimaryKey(used_id);
            JSONObject requestJSON = new JSONObject();
            requestJSON.put("amount", money);
            requestJSON.put("sn", basics.getRentDeviceSn());
            requestJSON.put("type", 2); // 机柜租赁费用
            requestJSON.put("used_id", used.getId());
            return BatteryJSONResult.build(2, "需发起支付", requestJSON);
        }

        Order order = orderService.selectOrderById(order_id);
        String out_trade_no = order.getOutOrderNo();
        AliPayEntity entity = _callApi();
        BatteryJSONResult queryResponse = AliPayUtils.tradeQuery(entity, out_trade_no);
        if (queryResponse.getCode() == 1 && OrderTradeStateEnum.PAY_SUCCESS.getCode() == (order.getTradeState())) {
            // 支付成功
            JSONObject requestJSON = new JSONObject();
            requestJSON.put("status", 1);
            requestJSON.put("order_id", order.getId());
            requestJSON.put("used_id", used_id);
            return BatteryJSONResult.build(1, "订单支付成功!", requestJSON);
        }
        return BatteryJSONResult.errorMsg("订单未支付");
    }


    /**
     * 充电线租借
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("lineScan")
    public BatteryJSONResult lineScan(HttpServletRequest request, @RequestBody JSONObject obj) {

        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }


        String sn = obj.getString("sn");
        Device device = deviceService.selectBySn(sn);
        if (device == null) {
            return BatteryJSONResult.errorMsg("该设备未激活！");
        }

        String devType = device.getDevType();
        if (!DevTypeEnum.R_LINE.getCode().equals(devType)) {
            return BatteryJSONResult.errorMsg("请扫正确的二维码！");
        }

        // 判断用户是否存在正在租借中的充电线订单
        UsedLineVO lineInRun = usedBasicsService.selectLineInRun(appUser.getId(), DateUtils.getNowDate(), sn);
        if (lineInRun != null) {
            JSONObject requestJSON = new JSONObject();
            requestJSON.put("sn", sn);
            requestJSON.put("used_id", lineInRun.getUsedId());
            requestJSON.put("password", lineInRun.getPassword());
            return BatteryJSONResult.build(2, "充电线已有订单", requestJSON);
        }

        // 查询对应的商家信息
        StoreInstall storeInstall = storeInstallService.selectByPrimaryKey(device.getStoreId());
//        if (storeInstall == null) {
//            return BatteryJSONResult.errorMsg("该设备线未部署！");
//        }

        JSONObject responseObj = new JSONObject();
        JSONArray array = new JSONArray();
        if (storeInstall != null) {
            if (StringUtils.isBlank(storeInstall.getChargerPrice())) {
                return BatteryJSONResult.errorMsg("门店未选择对应的线套餐");
            }
            JSONArray arr = JSON.parseArray(storeInstall.getChargerPrice());
            JSONObject zeroObj = new JSONObject();
            int xb = 0;
            for (int i = 0; i < arr.size(); i++) {
                boolean flag = false;
                JSONObject object = arr.getJSONObject(i);
                JSONObject mealObj = new JSONObject();
                String minute = object.getString("min");
                BigDecimal money = object.getBigDecimal("money");
                if (RLineMealTimeEnum.ONE_HOUR.type.equals(minute)) {
                    mealObj.put("value", "1小时" + money + "元");
                    mealObj.put("amount", money);
                    mealObj.put("time", minute);
                    flag = true;
                } else if (RLineMealTimeEnum.THREE_HOUR.type.equals(minute)) {
                    mealObj.put("value", "3小时" + money + "元");
                    mealObj.put("amount", money);
                    mealObj.put("time", minute);
                    flag = true;
                } else if (RLineMealTimeEnum.FIVE_HOUR.type.equals(minute)) {
                    mealObj.put("value", "5小时" + money + "元");
                    mealObj.put("amount", money);
                    mealObj.put("time", minute);
                    flag = true;
                } else if (RLineMealTimeEnum.TWELVE_HOUR.type.equals(minute)) {
                    mealObj.put("value", "12小时" + money + "元");
                    mealObj.put("amount", money);
                    mealObj.put("time", minute);
                    flag = true;
                }
                if (flag) {
                    if (xb == 0) {
                        mealObj.put("checked", true);
                        zeroObj = mealObj;
                    }
                    array.add(xb, mealObj);
                    xb++;
                }
            }
            responseObj.put("is_show", 1);
            Store store = storeService.selectByPrimaryKey(storeInstall.getStoreId());
            responseObj.put("storeName", store.getStoreName());
            responseObj.put("priceMeal", array);
            responseObj.put("leaseTime", zeroObj.getString("time"));
            responseObj.put("leaseMoney", zeroObj.getString("amount"));
        } else {
            JSONObject mealObj_1 = new JSONObject();
            mealObj_1.put("value", "1小时2元");
            mealObj_1.put("amount", 2);
            mealObj_1.put("time", RLineMealTimeEnum.ONE_HOUR.type);
            mealObj_1.put("checked", true);
            array.add(0, mealObj_1);

            JSONObject mealObj_2 = new JSONObject();
            mealObj_2.put("value", "3小时6元");
            mealObj_2.put("amount", 6);
            mealObj_2.put("time", RLineMealTimeEnum.THREE_HOUR.type);
            array.add(1, mealObj_2);

            JSONObject mealObj_3 = new JSONObject();
            mealObj_3.put("value", "5小时10元");
            mealObj_3.put("amount", 10);
            mealObj_3.put("time", RLineMealTimeEnum.FIVE_HOUR.type);
            array.add(2, mealObj_3);

            JSONObject mealObj_4 = new JSONObject();
            mealObj_4.put("value", "12小时20元");
            mealObj_4.put("amount", 20);
            mealObj_4.put("time", RLineMealTimeEnum.TWELVE_HOUR.type);
            array.add(3, mealObj_4);

            responseObj.put("is_show", 0);
            responseObj.put("storeName", "");
            responseObj.put("priceMeal", array);
            responseObj.put("leaseTime", mealObj_1.getString("time"));
            responseObj.put("leaseMoney", mealObj_1.getString("amount"));
        }
        // is vip or no
        boolean flag = false;
        Member member = memberService.selectTrueMember(appUser.getId());
        if (member != null) {
            if (YesOrNoEnum.NO.getCode().intValue() == member.getIsSuper().intValue()) {
                // 普通VIP
//                if (sn.equals(member.getDevSn())) {
                if (member.getStoreId().equals(device.getStoreId())) {
                    // 该VIP用户租借的是可免费的机柜，那么开始计算其的优惠金额
                    // 首先查询该VIP用户的租借次数
                    flag = true;
                }
            } else {
                flag = true;
            }
            if (flag) {
                // VIP对该机柜SN存在免费机会
                Integer dailyOrderLimit = member.getDailyOrderLimit(); // 每天免费订单数
                if (dailyOrderLimit > 0) {
                    // 查询该VIP用户今日已免费次数
                    Integer todayFreeCount = usedService.selectCountByTodayFree(appUser.getId());
                    if (todayFreeCount < dailyOrderLimit) {
                        // 今天用户已免费次数 小于等于 VIP用户的设置的免费次数
                        // 该用户可以免费试用充电线
                        JSONObject oneMeal = (JSONObject) array.get(0);
                        JSONObject responseOBJ = usedService.lineVipBorrow(appUser, device, oneMeal);
                        return BatteryJSONResult.build(3, "免费用户租借充电线", responseOBJ);
                    }
                }
            }
        }

        boolean needAuthPhone = false;
        if (StringUtils.isBlank(appUser.getMobile())) {
            Integer authPhoneNeedCount = Integer.parseInt(configService.selectConfigByKeyNoCache("sys.appuser.ali.line.warrantphone"));
            if (authPhoneNeedCount >= 0) {
                // 查询该用户租借次数
                Integer borrowCount = usedService.selectBorrowCount(appUser.getId());
                if (borrowCount >= authPhoneNeedCount) {
                    // 用于需要授权手机号
                    needAuthPhone = true;
                }
            }
        }
        if (needAuthPhone) {
            responseObj.put("need_tel", 1);
            responseObj.put("need_tel_tip_1", configService.selectConfigByKeyNoCache("sys.authtel.but.line.tips")); // 页面上授权手机号按钮文字
            responseObj.put("refuse_msg", configService.selectConfigByKeyNoCache("sys.authtel.line.refuse_msg")); // 用户拒绝授权手机号的提示
            responseObj.put("refuse_show", Integer.parseInt(configService.selectConfigByKeyNoCache("sys.authtel.line.refuse_show"))); // 拒绝是否需要提示文字 1 为需要 0 为不需要
            responseObj.put("refuse_after_borrow", Integer.parseInt(configService.selectConfigByKeyNoCache("sys.authtel.line.refuse_after_borrow"))); // 拒绝之后是否可以继续租借 1 可以继续租借 0 不允许继续租借
        } else {
            responseObj.put("need_tel", 0);
        }
        responseObj.put("sn", sn);
        return BatteryJSONResult.ok(responseObj);
    }


    /**
     * 租借充电线
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("LineBorrow")
    public BatteryJSONResult LineBorrow(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }

        String sn = obj.getString("sn");
        String time = obj.getString("time");
        String order_id = obj.getString("order_id");
        BigDecimal amount = obj.getBigDecimal("amount");

        Device device = deviceService.selectBySn(sn);
        if (device == null) {
            return BatteryJSONResult.errorMsg("该设备未激活!");
        }

        if (StringUtils.isBlank(order_id)) {
            // 订单未创建
            JSONObject requestJSON = new JSONObject();
            requestJSON.put("sn", sn);
            requestJSON.put("amount", amount);
            requestJSON.put("time", time);
            return BatteryJSONResult.build(3, "未创建订单", requestJSON);
        }

        // 查询用户是否支付
        Order order = orderService.selectOrderById(order_id);
        if (order == null) {
            return BatteryJSONResult.errorMsg("查询不到对应的支付订单，请联系管理员");
        }

        if (!OrderTradeStateEnum.PAY_SUCCESS.getCode().equals(order.getTradeState())) {
            return BatteryJSONResult.errorMsg("订单未支付");
        }

        JSONObject responseOBJ = usedService.lineBorrow(order, appUser, device);
        return BatteryJSONResult.ok(responseOBJ);
    }


    /**
     * 再次获取密码
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("againGetPwd")
    public BatteryJSONResult againGetPwd(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }
        String used_id = obj.getString("used_id");

        Used used = usedService.selectByPrimaryKey(used_id);
        if (used == null) {
            return BatteryJSONResult.errorMsg("未查询到对应的租借订单，请联系客服");
        }
        Order order = orderService.selectByPrimaryKey(used.getTrueOrderId());

        String lineTime = order.getExtend();

        UsedBasics basics = usedBasicsService.selectByPrimaryKey(used_id);

        String password = usedService.getPwByNewLine(basics.getRentDeviceId(), lineTime);
        JSONObject requestJSON = new JSONObject();
        requestJSON.put("password", password);
        requestJSON.put("used_id", used_id);
        return BatteryJSONResult.ok(requestJSON);
    }


    /**
     * 获取用户手机号
     *
     * @param request
     * @param obj
     * @return
     */
    @PostMapping("getPhoneNumber")
    public BatteryJSONResult getPhoneNumber(HttpServletRequest request, @RequestBody JSONObject obj) {
        String openid = request.getHeader("openid");
        if (StringUtils.isBlank(openid)) {
            return BatteryJSONResult.errorMsg("发送错误，请退出程序，重新进去!");
        }
        AppUser appUser = appUserService.selectByOpenId(openid);
        if (appUser == null) {
            return BatteryJSONResult.errorMsg("您未授权，请先授权登录!");
        }
        String response = obj.getString("encryptedData");
        if (StringUtils.isBlank(response)) {
            return BatteryJSONResult.errorMsg("请授权手机号!");
        }
        Map<String, String> openapiResult = JSON.parseObject(response,
                new TypeReference<Map<String, String>>() {
                }, Feature.OrderedField);
        String charset = "UTF-8";
        String encryptType = "AES";
        String content = openapiResult.get("response");
        String decryptKey = "jDI4QHOb5DjYxCSreEB8TQ==";
        String plainData = "";
        // {"code":"10000","msg":"Success","mobile":""}
        try {
            plainData = AlipayEncrypt.decryptContent(content, encryptType, decryptKey, charset);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        String mobile = null;
        JSONObject phoneJson = JSON.parseObject(plainData);
        if (phoneJson != null) {
            mobile = phoneJson.getString("mobile");
        }
        AppUser appUserUpdate = new AppUser();
        appUserUpdate.setId(appUser.getId());
        appUserUpdate.setMobile(mobile);
        appUserService.updateByPrimaryKeySelective(appUserUpdate);
        return BatteryJSONResult.ok();
    }


}
